//
//  CycBLEMessageCenter.m
//  Cycling
//
//  Created by cjg.mini on 2023/3/10.
//

#import "CycBLEMessageCenter.h"
#import "BaseRequest.h"

NSString * const CycBLEMessageCenterErrorDomain = @"CycBLEMessageCenterErrorDomain";

@interface CycBLEMessageCenter()

@property (nonatomic, strong) NSMutableArray *messageList;
@property (nonatomic, strong) NSMutableArray *blockList;
@property (nonatomic, strong) dispatch_queue_t messageQueue;
@property (nonatomic, strong) CycBleMessage *sendingMessage;
@property (nonatomic,   copy) CycBLEMessageCenterCompletionBlock sendingBlock;
@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic, assign) CGFloat timeOut;


@end

@implementation CycBLEMessageCenter

+ (CycBLEMessageCenter *)sharedInstance {
    
    static CycBLEMessageCenter *_sharedInstance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[CycBLEMessageCenter alloc] init];
    });
    return _sharedInstance;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        // data fc 数据
        [CycBLEManager sharedManager].receiveDatafcBlock = ^(NSData *data) {
            NSString *url = [NSString stringWithFormat:@"%@%@",BaseUrl,Cyc_API_Test];
            NSDictionary *parm = @{
                                   @"flag":@"fc数据",
                                   @"content":[self hexStringFromData:data]
                                   };

            [BaseRequest baseGET_New:url cache:NO autoHideLoading:NO parms:parm request:^(id  _Nullable resultObject, NSError * _Nullable error) {
                
            }];
        };
        
        // data out数据
        [CycBLEManager sharedManager].receiveDataoutBlock = ^(NSData *data) {
            NSString *url = [NSString stringWithFormat:@"%@%@",BaseUrl,Cyc_API_Test];
            NSDictionary *parm = @{
                                   @"flag":@"out数据",
                                   @"content":[self hexStringFromData:data]
                                   };

            [BaseRequest baseGET_New:url cache:NO autoHideLoading:NO parms:parm request:^(id  _Nullable resultObject, NSError * _Nullable error) {
                
            }];
            
            CycBleMessage *message = [[CycBleMessage alloc] initWithData:data];
            [self dispatchMessage:message error:nil];
        };

    }
    return self;
}

/// 发送消息
- (void)sendMessage:(CycBleMessage *)message withTimeOut:(CGFloat)timeOut completion:(CycBLEMessageCenterCompletionBlock)completion {
    self.timeOut = timeOut;
    [self enqueueMessage:message CompletionBlock:completion];
}

/// 加入block
- (void)addCompletionBlock:(CycBLEMessageCenterCompletionBlock)block forKey:(NSString *)key {
    if (block) {
        [self.blockList addObject:@{key:block}];
    }
}
/// 移除消息回调block -- 外部有单独使用该方法
- (void)removeCompletionBlockForKey:(NSString *)key {
    for (NSDictionary *blockDic in self.blockList) {
        if([blockDic.allKeys containsObject:key]){
            [self.blockList removeObject:blockDic];
        }
    }
}

/// 清除消息 --- 暂时不用外部处理
- (void)clearMessages {
    NSLog(@"-------------- 清除消息队列 ");
    if (self.timer.isValid) {
        [self.timer invalidate];
        self.timer = nil;
    }
    @synchronized(self) {
        [self.blockList removeAllObjects];
        [self.messageList removeAllObjects];
        self.sendingMessage = nil;
        self.sendingBlock = nil;
    }
}

/// 入列 ------- 异步串行
- (void)enqueueMessage:(CycBleMessage *)message CompletionBlock:(CycBLEMessageCenterCompletionBlock)block{
    if (self.messageQueue == nil) {
        self.messageQueue = dispatch_queue_create("CycBLEMessageCenter.messageQueue", DISPATCH_QUEUE_SERIAL);
    }
    /// 消息队列延时10毫秒执行  dispatch_async(self.messageQueue, ^{ });
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), self.messageQueue, ^{
        NSLog(@"=======================入列🍰🍰🍰%@",message.key);
        [self addCompletionBlock:block forKey:message.key]; // 加入block
        [self.messageList addObject:message];
        [self checkMessageQueue];
    });
    
}

- (void)checkMessageQueue {
    if (CycBLEManager.sharedManager.state != CYCBLEManagerStateSubscribed) {
        [self clearMessages];
        return;
    }
    
    if (self.messageList.count > 0 && self.blockList.count > 0) {
        if (self.sendingMessage && self.sendingBlock) {
            return;
        }
        CycBleMessage *message = [self.messageList firstObject];
        self.sendingMessage = message;
        
        NSDictionary *blockDic = self.blockList.firstObject;
        CycBLEMessageCenterCompletionBlock block = blockDic.allValues.firstObject;
        self.sendingBlock = block;
        
        [CycBLEManager.sharedManager sendData:message.extra];
        
        // 超时处理: 使用主线程Runloop来驱动timer
        dispatch_async(dispatch_get_main_queue(), ^{
            if (self.timer.isValid) {
                [self.timer invalidate];
                self.timer = nil;
            }
            self.timer = [NSTimer scheduledTimerWithTimeInterval:self.timeOut target:self selector:@selector(timerFired:) userInfo:nil repeats:NO];
        });
    }
}

- (void)timerFired:(NSTimer *)timer {
    dispatch_async(dispatch_get_main_queue(), ^{
        // 如果还处在发送状态，说明没有收到回应
        if (self.sendingMessage && self.messageList.count > 0) {
            CycBleMessage *message = self.sendingMessage;
            NSString *errorDescription = [NSString stringWithFormat:@"CYCMessage timeout error. [%@]", message.key];
            NSError *error = [NSError errorWithDomain:CycBLEMessageCenterErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey: errorDescription}];
            [self dispatchMessage:message error:error];
        }
    });
}

- (void)dispatchMessage:(CycBleMessage *)message error:(NSError *)error {
    
    CycBLEMessageCenterCompletionBlock block = self.sendingBlock;
    NSLog(@"🐯开启回调 == message.key:%@ == block:%@ == error:%@ == self.sendingMessage.key:%@ ------ blocklist:%lu ====== messagelist:%lu",message.key,block,error,self.sendingMessage.key,(unsigned long)self.blockList.count,(unsigned long)self.messageList.count);
    
    if (block) {
        if (error) {
            block(error, nil);
        } else {
            block(nil, message.extra);
        }
    }
    [self dequeueMessage];
}

/// 出列
- (void)dequeueMessage {
    if (self.messageQueue == nil) {
        return;
    }
    if (self.timer.isValid) {
        [self.timer invalidate];
        self.timer = nil;
    }
    
    dispatch_async(self.messageQueue, ^{
        @synchronized(self) {
            if (self.messageList.count > 0 && self.blockList.count > 0) {
                if (self.sendingMessage) {
                    NSLog(@"=======================出列🍰🍰🍰%@",self.sendingMessage.key);
                    [self.messageList removeObject:self.sendingMessage];
                    NSDictionary *blockDic = nil;
                    for (NSDictionary *dic in self.blockList) {
                        CycBLEMessageCenterCompletionBlock block = dic.allValues.firstObject;
                        if (block == self.sendingBlock) {
                            blockDic = dic;
                        }
                    }
                    [self.blockList removeObject:blockDic];
                    self.sendingMessage = nil;
                    self.sendingBlock = nil;
                }
            }
            /// 消息队列延时20毫秒执行  dispatch_async(self.messageQueue, ^{ });
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.03 * NSEC_PER_SEC)), self.messageQueue, ^{
                [self checkMessageQueue];
            });
        }
    });
}

#pragma mark - Lazy
- (NSMutableArray *)messageList {
    if (!_messageList) {
        _messageList = [[NSMutableArray alloc] init];
    }
    return _messageList;
}

- (NSMutableArray *)blockList {
    if (!_blockList) {
        _blockList = [NSMutableArray arrayWithCapacity:1];
    }
    return _blockList;
}

//data转换为十六进制的string
-(NSString *)hexStringFromData:(NSData *)myD{
    
    Byte *bytes = (Byte *)[myD bytes];
    //下面是Byte 转换为16进制。
    NSString *hexStr=@"";
    for(int i=0;i<[myD length];i++)
    {
        NSString *newHexStr = [NSString stringWithFormat:@"%x",bytes[i]&0xff];///16进制数
        if([newHexStr length]==1)
            hexStr = [NSString stringWithFormat:@"%@0%@",hexStr,newHexStr];
        else
            hexStr = [NSString stringWithFormat:@"%@%@",hexStr,newHexStr];
    }
    NSLog(@"hex = %@",hexStr);
    return hexStr;
}

@end
